/**
  ******************************************************************************
  * @file        iec_sys.h
  * @author      古么宁
  * @brief       iec101 规约系统层文件，进行系统的一些基本的定义
  * @date        2019-04-10
  ******************************************************************************
  *
  * COPYRIGHT(c) 2019 GoodMorning
  *
  ******************************************************************************
  */
#ifndef _IEC_SYS_H_
#define _IEC_SYS_H_

#ifndef     IEC_BIG_ENDIAN
    #define IEC_BIG_ENDIAN     0x3412
#endif

#ifndef     IEC_LITTLE_ENDIAN
    #define IEC_LITTLE_ENDIAN  0x1234
#endif

/** 协议栈使用小端 cpu */
#define IEC_ENDIAN               IEC_LITTLE_ENDIAN

/** 使能 iec101 主站功能 */
#define ENABLE_IEC101_MASTER     (1)

/** 使能 iec101 从站功能 */
#define ENABLE_IEC101_SLAVE      (1)

/** 使能 iec104 主站功能 */
#define ENABLE_IEC104_MASTER     (1)

/** 使能 iec104 从站功能 */
#define ENABLE_IEC104_SLAVE      (1)

/** 使能调试信息打印，为 0 时不输出调试信息 */
#define ENABLE_DEBUG_INFO        (3)

/** 使能协议栈的文件传输功能 */
#define ENABLE_FILE_TRANS        (1)

/** 启用内部的内存管理机制。方便在一些没有操作系统的地方进行移植 */
#define ENABLE_IEC_MEMMANG       (1)

/** 多线程支持，需要提供线程互斥量实现 */
#define ENABLE_MULTITHREAD       (1)

/** 报文解析打印输出 */
#define ENABLE_PKT_PARSER        (1)

/** 104 使能 */
#define ENABLE_IEC104_MODE       (ENABLE_IEC104_MASTER || ENABLE_IEC104_SLAVE)

/** 101 使能 */
#define ENABLE_IEC101_MODE       (ENABLE_IEC101_MASTER || ENABLE_IEC101_SLAVE)

/** 10x 主站功能使能 */
#define ENABLE_IEC10x_MASTER     (ENABLE_IEC104_MASTER || ENABLE_IEC101_MASTER)

/** 10x 从站功能使能 */
#define ENABLE_IEC10x_SLAVE      (ENABLE_IEC104_SLAVE  || ENABLE_IEC101_SLAVE)

// ------------------------- 协议栈基本类型 -------------------------

#if 1
	#include <stdint.h>
	#include <stddef.h>
#else
	/* 如果不引入 stdint.h 则需要实现以下类型 */
	typedef unsigned char  uint8_t ;
	typedef unsigned short uint16_t;
	typedef unsigned int   uint32_t;
#endif


// ------------------------- 协议栈多线程互斥 -------------------------

#if (ENABLE_MULTITHREAD == 0) 
	/* 如果没有多线程处理，互斥锁相关宏定义可以留空 */
    typedef int iec_sys_mutex_t ;
    #define iec_sys_mutex_lock(x)
    #define iec_sys_mutex_unlock(x)
    #define iec_sys_mutex_init(x)
	#define iec_sys_mutex_deinit(x)

#else // 需要多线程支持

    #include <pthread.h>

    // 定义互斥锁类型
    typedef pthread_mutex_t iec_sys_mutex_t ;

    // 定义基本的互斥锁操作
    #define iec_sys_mutex_lock(x)   pthread_mutex_lock((x))
    #define iec_sys_mutex_unlock(x) pthread_mutex_unlock((x))
    #define iec_sys_mutex_init(x)   pthread_mutex_init((x), NULL)
	#define iec_sys_mutex_deinit(x) pthread_mutex_destroy((x))
#endif


// ------------------------- 协议栈内存管理 -------------------------

#if (ENABLE_IEC_MEMMANG == 1) 

    #define BUF_POOL_SIZE (10*1024)  // 内存池大小
    extern void  * iec_malloc(size_t wantedsize) ;
    extern void    iec_free(void * buff) ;

#else  // 不启用协议栈自带的内存管理，需要用户提供基本的内存管理 

    #include <stdlib.h>
    #define iec_malloc(size)    malloc(size)
    #define iec_free(buf)       free(buf)

#endif


// ------------------------- 协议栈打印信息 -------------------------


#if (ENABLE_DEBUG_INFO > 0)
	/// 系统打印等级等于 1 时，只打印错误信息
	#include <stdio.h>
    #define IEC_MSG(...) printf(__VA_ARGS__)
#else
	#define IEC_MSG(...)
#endif


#ifndef container_of
//------------------------------------------------------------------
	#ifndef offsetof
		//#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)// 获取"MEMBER成员"在"结构体TYPE"中的位置偏移
		#include <stddef.h>
	#endif

	#ifndef __GNUC__
		// 根据"结构体(type)变量"中的"域成员变量(member)的指针(ptr)"来获取指向整个结构体变量的指针
		#define container_of(ptr, type, member)  ((type*)((char*)ptr - offsetof(type, member)))
		// 此宏定义原文为 GNU C 所写，如下，有些编译器只支持 ANSI C /C99 的，所以作以上修改
	#else
		#define container_of(ptr, type, member) ({          \
			const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
			(type *)( (char *)__mptr - offsetof(type,member) );})
	#endif
//------------------------------------------------------------------
#endif


#endif
